package com.zzl.alligator.framework.job;

import com.zzl.alligator.common.util.SpringUtils;
import com.zzl.alligator.management.vote.service.IVoteSubjectService;
import lombok.extern.slf4j.Slf4j;
import org.quartz.DisallowConcurrentExecution;
import org.quartz.Job;
import org.quartz.JobDataMap;
import org.quartz.JobDetail;
import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException;

import java.io.Serializable;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;

/**
 * 通用Job 任务可以直接写入 此类中
 * <p>
 * 实现序列化接口、防止重启应用出现quartz Couldn't retrieve job because a required class was not found 的问题
 * Job 的实例要到该执行它们的时候才会实例化出来。每次 Job 被执行，一个新的 Job 实例会被创建。
 * 其中暗含的意思就是你的 Job 不必担心线程安全性，因为同一时刻仅有一个线程去执行给定 Job 类的实例，甚至是并发执行同一 Job 也是如此。
 *
 * @author zhouziliang
 * @DisallowConcurrentExecution 保证上一个任务执行完后，再去执行下一个任务，这里的任务是同一个任务
 * @since 2020/7/10
 */
@DisallowConcurrentExecution
@Slf4j
public class VoteJob implements Job, Serializable {

    private static final long serialVersionUID = 1L;

    /**
     * 调用入口
     *
     * @param context 上下文
     * @throws JobExecutionException 异常
     */
    @Override
    public void execute(JobExecutionContext context) throws JobExecutionException {
        JobDetail jobDetail = context.getJobDetail();
        JobDataMap dataMap = jobDetail.getJobDataMap();

        /**
         * 获取任务中保存的方法名字，动态调用方法
         */
        String methodName = dataMap.getString("jobMethodName");
        String voteIdStr = dataMap.getString("methodParam");
        Long subjectId = Long.valueOf(voteIdStr);

        try {
            VoteJob job = new VoteJob();
            Method method = job.getClass().getMethod(methodName);
            method.invoke(job, subjectId);
        } catch (NoSuchMethodException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } catch (InvocationTargetException e) {
            e.printStackTrace();
        } catch (Exception e) {
            log.error("任务异常", e);
        }
    }

    /**
     * 启动投票
     */
    public void startVote(Long subjectId) {
        log.info("启动编号为{}的投票", subjectId);
        IVoteSubjectService subjectService = SpringUtils.getBean(IVoteSubjectService.class);
        subjectService.startSubject(subjectId);
        log.info("启动编号为{}的投票结束", subjectId);
    }

    /**
     * 结束投票
     */
    public void cutOffVote(Long subjectId) {
        log.info("截止编号为{}的投票", subjectId);
        IVoteSubjectService subjectService = SpringUtils.getBean(IVoteSubjectService.class);
        subjectService.cutOffSubject(subjectId);
        log.info("截止编号为{}的投票结束", subjectId);
    }

}
